using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using FireStarter.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Microsoft.CSharp;

namespace FireStarter.CodeGeneration
{
    public class BoProjectGenerator: ProjectGenerator
    {
        public override Result Generate()
        {
            CheckRequiredPropertiesSet();
            if (SolutionGenerator.ModelClasses == null) throw new PropertyMissingException("ModelClasses");
            Directory.CreateDirectory(ProjectPath);

            BoProjectTemplateLoader boProjectTemplateLoader = new BoProjectTemplateLoader();

            string contents = boProjectTemplateLoader.GetAssemblyInfo(ProjectName);
            string assemblyInfoFileName = Utilities.CreateFile(ProjectPath, "Properties\\AssemblyInfo.cs", contents);
            
            string projectFileName = Path.Combine(ProjectPath, ProjectName + ".csproj");
            ProjectFileManager projectFileManager = new ProjectFileManager(projectFileName, OutputType.Library, SolutionGenerator.CodeTemplate);
            
            BoProjectTemplateLoader templateLoader = new BoProjectTemplateLoader();
            CreateBoClassFiles(templateLoader, projectFileManager, SolutionGenerator.ModelClasses);
            //CreateBoClassFiles(projectFileManager);

            CreateBOBroker(boProjectTemplateLoader, projectFileManager);
            CreateClassDefsXML(projectFileManager);

            projectFileManager.AddReference(Path.Combine(SolutionGenerator.HabaneroReferencePath, "Habanero.Base.dll"));
            projectFileManager.AddReference(Path.Combine(SolutionGenerator.HabaneroReferencePath, "Habanero.BO.dll"));
            projectFileManager.AddReference(Path.Combine(SolutionGenerator.HabaneroReferencePath, "Habanero.DB.dll"));

            projectFileManager.SaveProjectFile();
            return new Result(true);
        }

        private void CreateBoClassFiles(BoProjectTemplateLoader templateLoader, ProjectFileManager projectFileManager, IList<IModelClass> modelClasses)
        {
            string boProjectName = SolutionGenerator.ModelSolution.BOProjectName;

            foreach (IModelClass modelClass in modelClasses)
            {
                if (!modelClass.GenerateCode) continue;
                string contents = templateLoader.GetBoClass_Main(ProjectName, boProjectName, modelClass);
                string mainClassFileName = String.Format("{0}.cs", modelClass.ClassName);
                string mainFilePath = Utilities.CreateFile(ProjectPath, mainClassFileName, contents, false);
                projectFileManager.AddCodeFile(mainFilePath);

                string fileName = modelClass.ClassName;
                fileName = Path.Combine(ProjectPath, fileName);
                if (modelClass.NeedsRegeneration || !File.Exists(fileName))
                {
                    contents = templateLoader.GetBoClass_Generated(ProjectName, boProjectName, modelClass);
                    string defClassFileName = String.Format("{0}.Def.cs", modelClass.ClassName);
                    string defFilePath = Utilities.CreateFile(ProjectPath, defClassFileName, contents, true);
                    projectFileManager.AddCodeFile(defFilePath, mainFilePath);
                }
            }
        }

        private void CreateBOBroker(BoProjectTemplateLoader boProjectTemplateLoader, ProjectFileManager projectFileManager)
        {
            string contents = boProjectTemplateLoader.GetBroker(ProjectName, SolutionGenerator.ModelSolution.ApplicationName);
            string brokerName = Utilities.CreateFile(ProjectPath, "BOBroker.cs", contents);
            projectFileManager.AddCodeFile(brokerName);
        }

        private void CreateClassDefsXML(ProjectFileManager projectFileManager)
        {
            string classDefsName = XmlUtilities.CreateXmlFile(ProjectPath, "ClassDefs.xml", SolutionGenerator.ClassDefsString, true, null);
            projectFileManager.AddEmbeddedResourceFile(Path.Combine(ProjectPath, classDefsName));
        }
    }
}
